home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 52
/
Aminet 52 (2002)(GTI - Schatztruhe)[!][Dec 2002].iso
/
Aminet
/
misc
/
emu
/
Apex-src.lha
/
AMIGAHAN.68K
< prev
next >
Wrap
Text File
|
2001-09-30
|
44KB
|
1,273 lines
;AMIGAHAN.68K AUG-06-90 (also see INFOSTR)
;Console handler for the Amiga
;Written by Loren Blaney
;This is based on QUMEHANA.68K
;
;Revision history:
;APR-10-87, Original.
;JUN-88, Changed dimensions to 640x240, added installable fonts,
; setable colors, faster scrolls, characters that can be positioned
; anywhere (not just on character cell boundaries), CHKUSR, fixed CAPS
; LOCK problem, and auto-repeat.
;JUL-06-88, Fixed DIV bug (dividend is 32 bits).
;AUG-06-90, Added address of font table to GETINFO array.
;
;Notes:
;Beware of stack space near end. If this program is made a few bytes
; bigger, the stack will eat it.
;Also, there is an interrupt other than level 2 that occurs at boot up.
;
;This handler differs from the Apple handler in that a <CR> does not
; erase the rest of the line, tabs are not deleted correctly when using
; the "<--" key. Null characters are not suppressed. This handler does
; not the have the <ESC> cursor commands of the Apple, but it does have
; a cleaner line delete (CTRL-X) and it has an undelete command (CTRL-Z)
;Locations in INTA.68K:
;WARNING: these routines may clobber D0 and A6
CLEAR EQU $8F0 ;40 clear the current bit map
BITMAP EQU $A88 ;108 BITMAP(ADDR, WIDTH, HEIGHT, DEPTH)
BITMAP2 EQU $A8E ;109 BITMAP2(MAGX, Y, OFFX, Y, INVX, Y)
VIEW EQU $A94 ;110, VIEW(ADDR,BPLCON0)
RASTER EQU $B5A ;Location of current bit map
WIDTH EQU $B5E ;Dimensions of RASTER in pixels
HEIGHT EQU $B62
DEPTH EQU $B66
MAGX EQU $B6A ;Parameters affecting how coordinates
MAGY EQU $B6E ; are remapped from specified to
OFFSETX EQU $B72 ; actual hardware values
OFFSETY EQU $B76
INVERTX EQU $B7A
INVERTY EQU $B7E
X0 EQU $B82 ;Graphics coordinates (these might have
Y0 EQU $B86 ; been remapped by the above parameters)
X1 EQU $B8A
Y1 EQU $B8E
COLOR EQU $B92 ;Only lowest byte specifies color reg.
MODES EQU COLOR+2 ;Bit 0: complement
;Bit 1: fast (i.e. don't clear zeros)
TEXTURE EQU COLOR ;For dotted lines, etc. Ones indicate
; where points are NOT plotted. 16 bits.
NOLIST
INCLUDE SYSPAG ;Get the system definitions
LIST
ORG $7F240 ;*** DEBUG ***
START EQU @ ;Address where this handler starts
;======================================================================
;Buffered console handler (device #0)
;
CONHAN0 DC.L OPENI0 ;0 = OPENI
DC.L OPENO0 ;1 = OPENO
DC.L CHIN0 ;2 = CHIN
DC.L CHOUT0 ;3 = CHOUT
DC.L CLOSE0 ;4 = CLOSE
DC.L GETINFO ;5 = Get info
DC.L DUMMY ;6 = Spare
DC.L CURSOR1 ;7 = Position cursor
DC.L DUMMY ;8
DC.L DUMMY ;9
DC.L DUMMY ;10
DC.L SHOCUR ;11 = Turns the cursor on/off
DC.L BUTES ;12 = Set display attributes
;----------------------------------------------------------------------
;Open (initialize) the buffered keyboard for input.
; This will discard any characters in the buffer and any pending
; characters from the keyboard (type-ahead buffer).
;
OPENI0 MOVE.L #LINBUF,LINPTRF ;Reset line buffer fill & empty pointers
MOVE.L #LINBUF,LINPTRE
BRA OPENI1 ;(PBRA) Also open unbuffered keyboard
;----------------------------------------------------------------------
;Open (initialize) buffered terminal for output
;
OPENO0 BSR OPENO ;Initialize low-level output routines
BRA CRLF1 ;(PBRA)
;----------------------------------------------------------------------
;Get a character from the buffered keyboard and return it in D0.
;The buffered keyboard handles the following control characters:
; <-- (CTRL-H): Delete back one character
; --> (CTRL-U): Move cursor forward one character
; DEL: Delete back one character (same as CTRL-H)
; CTRL-X: Delete the entire line
; CTRL-Z: Undelete the line
; WARNING: the "<--" and "DEL" keys will not handle tabs correctly.
;
CHIN0 MOVEM.L A0/A1,-(SP) ;Save registers
MOVEA.L LINPTRF,A0 ;Get the line buffer pointers
MOVEA.L LINPTRE,A1
CMPA.L A0,A1 ;Does fill pointer = empty pointer?
BNE.S CHIN010 ;Branch if not
BSR.S FILLBUF ;Get a line of characters from keyboard
CHIN010 MOVEQ #0,D0
MOVE.B (A1)+,D0 ;Get character at empty pointer
MOVE.L A0,LINPTRF ;Save the pointers
MOVE.L A1,LINPTRE
MOVEM.L (SP)+,A0/A1 ;Restore registers
RTS
;----------------------------------------------------------------------
;Get a line of characters from the keyboard and put them into LINBUF.
; Registers D0, A0, and A1 are destroyed.
;
FILLBUF LEA LINBUF,A0 ;Reset the pointers to the start of
MOVEA.L A0,A1 ; the line buffer
FB00 BSR GETKEYX ;Get character from keyboard
; (check CTRL-C, etc.)
CMPI.B #DEL,D0 ;Is it a delete character?
BEQ.S FB05 ;Branch if it is
CMPI.B #BS,D0 ;Is it a backspace (back arrow)?
BNE.S FB10 ;Branch if not
FB05 CMPA.L #LINBUF,A0 ;Is it the beginning of the buffer?
BEQ.S FB00 ;Branch if so (don't delete anything)
SUBQ.L #1,A0 ;Back up 1 character in the line buffer
MOVEQ #BS,D0 ;Delete the character on the screen
BSR CHOUT1 ;Back up
MOVEQ #SPACE,D0 ;Space it out
BSR CHOUT1
MOVEQ #BS,D0 ;Back up
BSR CHOUT1
BRA FB00 ;Go get next keystroke
FB10 CMPI.B #FWDSP,D0 ;Forward (right) arrow?
BNE.S FB20 ;Branch if not
CMPI.B #CR,(A0) ;Is it at the end of the input line?
BEQ.S FB00 ;Branch if it is (ignore it)
CMPA.L #LINBUFE,A0 ;Is it beyond the end of the buffer?
BHS.S FB00 ;Branch if it is (ignore it)
MOVE.B (A0)+,D0 ;Echo char to move forward on screen
BSR CHOUT1
BRA.S FB00 ;Go get next keystroke
FB20 CMPI.B #'X'-CTRL,D0 ;CTRL-X (line delete)?
BNE.S FB30 ;Branch if not
BSR DELLINE ;Delete the line
BRA.S FB00
FB30 CMPI.B #'Z'-CTRL,D0 ;CTRL-Z (regurge previous line buffer)?
BNE.S FB50 ;Branch if not
BSR DELLINE ;Delete anything on the line & reset A0
FB35 MOVE.B (A0),D0 ;Get character from previous buffer
CMPI.B #CR,D0 ;Is it a carriage return?
BEQ.S FB00 ;Branch if yes, we're done
BSR CHOUT1 ;Echo this character
CMPA.L #LINBUFE,A0 ;Are we beyond the end of the buffer?
BHS.S FB00 ;Branch if yes, we're done
ADDQ.L #1,A0 ;Increment fill pointer
BRA.S FB35 ;Loop until done
;The last character in the line buffer may be a <CR> but anything else
; is an error.
FB50 MOVE.B D0,(A0)+ ;Always store the character
CMPI.B #CR,D0 ;Was it a carriage return?
BEQ.S FB90 ;Exit if it was
CMPA.L #LINBUFE-1,A0 ;Is the buffer full? (leave room for CR)
BLO.S FB85 ;Branch if it is not - go echo char
FB80 SUBQ.L #1,A0 ;Move fill pointer back
MOVEQ #BEL,D0 ;Buffer is full so just beep
FB85 BSR CHOUT1
BRA FB00 ;Loop until carriage return
FB90 BSR CHOUT1 ;Echo the carriage return
RTS
;----------------------------------------------------------------------
;Delete the line buffer. This deletes it from the screen and resets the
; fill pointer (A0) to the beginning of the buffer.
; Register D0 is destroyed.
;
DELLINE CMPA.L #LINBUF,A0 ;Are we at the beginning of the buffer?
BEQ.S DELL90 ;Branch if we are - we're all done
SUBQ.L #1,A0 ;Backup one character in the line buffer
MOVEQ #BS,D0 ;Delete the character on the screen:
BSR CHOUT1 ; back up
MOVEQ #SPACE,D0 ; space it out
BSR CHOUT1
MOVEQ #BS,D0 ; back up
BSR CHOUT1
BRA.S DELLINE ;Loop for all characters
DELL90 RTS
;----------------------------------------------------------------------
;Output character in D0 to the terminal
;
CHOUT0 BRA CHOUT1 ;(PBRA) same as for device # 1
;----------------------------------------------------------------------
;Close the terminal
;
CLOSE0 BRA CLOSE1 ;(PBRA) same as for device # 1
;======================================================================
;Unbuffered console handler (device #1)
;
CONHAN1 DC.L OPENI1 ;0 = OPENI
DC.L OPENO1 ;1 = OPENO
DC.L CHIN1 ;2 = CHIN
DC.L CHOUT1 ;3 = CHOUT
DC.L CLOSE1 ;4 = CLOSE
DC.L GETINFO ;5 = Get info
DC.L DUMMY ;6 = Spare
DC.L CURSOR1 ;7 = Position cursor
DC.L CHKUSR ;8 = Check for CTRL-C, CTRL-S, CTRL-P
DC.L GETKEYZ ;9 = Wait for and return a key's value
DC.L KEYHIT ;10 = D0 = 'true' if key was hit
DC.L SHOCUR ;11 = Turns the cursor on/off
DC.L BUTES ;12 = Set display attributes
;----------------------------------------------------------------------
;Open (initialize) keyboard for input.
; This will discard any characters in the type ahead buffer.
;
OPENI1 BSR OPENI ;Initialize low-level input routines
MOVE.L D0,-(SP) ;Save D0
MOVEQ #FALSE,D0 ;Turn off the cursor flasher
BSR SHOCUR
OPI105 BSR KEYHIT ;Is a key pressed?
BEQ.S OPI110 ;Branch if not
BSR GETKEYX ;If so, eat it (check for CTRL-C, etc.)
BRA.S OPI105 ;Loop unitl all characters are flushed
OPI110 MOVE.L (SP)+,D0 ;Restore D0
DUMMY RTS
;----------------------------------------------------------------------
;Open (initialize) terminal screen for output.
;
OPENO1 MOVE.L D0,-(SP) ;Save D0
BSR OPENO ;Initialize low-level output routines
MOVEQ #FALSE,D0 ;Turn off the cursor flasher
BSR SHOCUR
BSR CRLF1 ;Move to the start of a new line
MOVE.L (SP)+,D0 ;Restore D0
RTS
;----------------------------------------------------------------------
;Get a character from the keyboard, echo it, and return it in D0.
;
CHIN1 BSR GETKEYX ;Get the char (check for CTRL-C, etc.)
BRA CHOUT1 ;(PBRA) Echo it
;----------------------------------------------------------------------
;Output the character in D0.
; Handle some special characters: BELL, TAB, CR, & FF.
;
CHOUT1 CMPI.B #$20,D0 ;Is it a control character?
BHS BYTEOUT ;(PBHS) Branch if not
CMPI.B #TAB,D0 ;Is it a TAB character?
BNE.S CHO120 ;Branch if not
BRA DOTAB ;(PBRA) do tab and return
CHO120
CMPI.B #CR,D0 ;Is it a carriage return?
BNE.S CHO130 ;Branch if not
BRA CRLF1 ;(PBRA) Start a new line
CHO130
CMPI.B #FF,D0 ;Is it a form feed?
BNE.S CHO140 ;Branch if not
BRA HOMER ;(PBRA) Do home erase and return
CHO140
CMPI.B #BEL,D0 ;Is it a bell?
BNE.S CHO150 ;Branch if not
BRA BEEP ;(PBRA) Make beep noise and return
CHO150
CMPI.B #LF,D0 ;Is it a line feed?
BNE.S CHO160 ;Branch if not
RTS ;Ignore it (these are still a problem)
CHO160
CMPI.B #BS,D0 ;Is it a backspace?
BNE.S CHO170 ;Branch if not
SUBQ.W #8,X0+2 ;Decrement X position
RTS ;WARNING: THIS CAN UNDERFLOW ??
CHO170
BRA BYTEOUT ;(PBRA) Output the character and return
;----------------------------------------------------------------------
;Close the terminal (nothing required).
;
CLOSE1 RTS
;----------------------------------------------------------------------
;Return the address of the information array in D0
;
GETINFO MOVE.L #INFO,D0
RTS
INFO DC.L START ;0 Starting and ending addresses of
DC.L END ;1 this handler
DC.L INFOSTR ;2 Description
DC.L FONT ;3 Address of font table
DC.L 0 ;4 (not used)
DC.L $00240EC9 ;5 Colors: background (high), text (low)
DC.L $08800000 ;6 Cursor color
INFOSTR ASCII 'AMIGAHAN AUG-06-90 Amiga console handler'
DC.B 0
;----------------------------------------------------------------------
;Position the cursor to X,Y.
;Inputs:
; High byte of D0 = X = Column
; Low byte of D0 = Y = Line =
;
;Register usage:
; D1 = Cursor X position
; D2 = Cursor Y position
;
CURSOR1 MOVEM.L D0-D2,-(SP) ;Save registers
MOVEQ #0,D2 ;Cursor Y position
MOVE.B D0,D2 ;D2.L = Y
ROR.W #8,D0
MOVEQ #0,D1 ;Cursor X position
MOVE.B D0,D1 ;D1.L = X
MOVE.W WIDTH+2,D0 ;D0:= WIDTH/8
LSR.W #3,D0 ;Width in characters
CUR10 CMP.B D0,D1 ;Check for limits
BLO.S CUR20
SUB.B D0,D1
BRA.S CUR10
CUR20
MOVE.L HEIGHT,D0 ;D0:= HEIGHT/FHEIGHT
DIVU FHEIGHT+2.L,D0 ;Height in characters
CUR30 CMP.B D0,D2
BLO.S CUR40
SUB.B D0,D2
BRA.S CUR30
CUR40
ASL.W #3,D1 ;X0:= D1 *8 (8 = FWIDTH)
MOVE.W D1,X0+2
MULU FHEIGHT+2.L,D2 ;Y0:= D2 * FHEIGHT
MOVE.W D2,Y0+2
MOVEM.L (SP)+,D0-D2 ;Restore registers
RTS
;----------------------------------------------------------------------
;Check for and handle CTRL-S, CTRL-P, and CTRL-C.
;
CHKUSR TST.B CHKUSRF ;Is CHKUSR disabled (usually by ED)?
BEQ.S CKU99 ;Branch if so - exit
MOVEM.L D0/A0,-(SP) ;Save registers
BSR KEYHIT ;Was a key pressed?
BEQ.S CKU90 ;Branch if not - exit
MOVEA.L KEYFILL-@-2(PC),A0 ;Get last keystroke in circular (type
SUBQ.L #1,A0 ; ahead) buffer. Backup a character
CMPA.L #KEYSTRT,A0 ;Did we back out of the buffer?
BHS.S CKU10 ;Branch if not
MOVEA.L #KEYEND-1,A0 ;Point to last char in circular buffer
CKU10 MOVE.B (A0),D0 ;Get last keystroke character
CMPI.B #'C'-CTRL,D0 ;Is it a CTRL-C?
BNE.S CKU20 ;Branch if not
MOVE.L A0,KEYFILL.L ;Eat the CTRL-C
MOVEM.L (SP)+,D0/A0 ;Restore registers (be conservative)
JMP VEXIT ;Take program exit vector
CKU20
CMPI.B #'P'-CTRL,D0 ;Is it a CTRL-P?
BNE.S CKU30 ;Branch if not
MOVE.L A0,KEYFILL.L ;Eat the CTRL-P
MOVEM.L (SP)+,D0/A0 ;Restore registers (be conservative)
JMP VABORT ;Take program abort vector
CKU30
CMPI.B #'S'-CTRL,D0 ;Is it a CTRL-S?
BNE.S CKU90 ;Branch if not
MOVE.L A0,KEYFILL.L ;Eat the CTRL-P
CKU35 CMPA.L KEYFILL-@-2(PC),A0 ;Wait for a keystroke
BEQ.S CKU35
MOVE.L A0,KEYFILL.L ;Eat this keystroke
CKU90 MOVEM.L (SP)+,D0/A0 ;Restore registers
CKU99 RTS
;----------------------------------------------------------------------
;Get a character from the keyboard (or command file) and return it in D0
; check for CTRL-C, etc.
;
GETKEYX MOVEQ #TRUE,D0 ;Turn on the cursor flasher
BSR SHOCUR
BSR GETKEYZ ;Get the character (from the keyboard
; or from a .CMD file)
MOVE.L D0,-(SP)
MOVEQ #FALSE,D0 ;Turn off the cursor flasher
BSR SHOCUR
MOVE.L (SP)+,D0
CMPI.B #'C'-CTRL,D0 ;Is it a CTRL-C?
BNE.S GKX20 ;Branch if not
JMP VEXIT ;Take program exit vector
GKX20
CMPI.B #'P'-CTRL,D0 ;Is it a CTRL-P?
BNE.S GKX30 ;Branch if not
JMP VABORT ;Take program abort vector
GKX30
RTS
;----------------------------------------------------------------------
;Get a character from the keyboard or command file and return it in D0.
; Command (.CMD) files are initiated by APEX.XPL (DOCMD), which fills
; the command buffer (CMDBUF) with the characters and sets the CMDMOD
; flag. The command buffer physically occupies the same space as the
; keyboard buffer, but they are logically two separate buffers.
;
GETKEYZ TST.B CMDMOD ;Are we in command mode?
BEQ.S GKZ20 ;Branch if not
MOVE.L A6,-(SP) ;Get character from command buffer
MOVEA.L CMDPTR,A6 ; at CMDPTR
MOVEQ #0,D0
MOVE.B (A6)+,D0 ;Bump pointer and save it
MOVE.L A6,CMDPTR
MOVEA.L (SP)+,A6
CMPI.B #EOF,D0 ;Is this the end of the command file?
BNE.S GKZ90 ;Branch if not -- exit with char in D0
MOVE.B #FALSE,CMDMOD ;Turn off command mode
GKZ20 BSR GETKEY ;Get the character from keyboard
GKZ90 RTS
;----------------------------------------------------------------------
;Space over to next tab stop
;
DOTAB MOVE.L D0,-(SP) ;Save register
DOTAB10 MOVEQ #SPACE,D0 ;Output a space character
BSR BYTEOUT
MOVE.W X0+2,D0 ;Are we at the next tab stop?
ANDI.B #$38,D0 ;Every 8th character, 8 pixels wide
BNE.S DOTAB10 ;Branch if not
MOVE.L (SP)+,D0 ;Restore register
RTS
;----------------------------------------------------------------------
;Clear the screen and home to upper-left corner.
;
HOMER MOVEM.L D0/A6,-(SP) ;Save registers
JSR CLEAR ;(PJMP)
MOVEM.L (SP)+,D0/A6 ;Restore registers
RTS
;----------------------------------------------------------------------
;Start a new line on the terminal.
;
CRLF1 CLR.W X0+2 ;Reset X position to 0
MOVE.W D0,-(SP)
MOVE.W FHEIGHT+2.L,D0 ;Move down a line
ADD.W D0,Y0+2
MOVE.W (SP)+,D0
BRA SCROLL ;(PRBA) Check for scroll and adjust the
; cursor position if necessary
;----------------------------------------------------------------------
;Routine to turn the cursor indicator on/off.
; If D0 # 0 (true), the cursor is turned on.
;
;(Eventually add a sprite)
SHOCUR
RTS
;----------------------------------------------------------------------
;Set the display attributes according to D0.
; D0 contains a 4-bit array.
; (The terminal should be set up so that attributes are active to the
; end of the page.)
;
BUTES
RTS
;======================================================================
;Lowest level I/O routines:
;
SCREEN EQU $60000 ;Address of screen buffer
CHIPREG EQU $DFF000 ;Base address of chip registers
;Offsets to chip registers:
DMACONR EQU $02 ;DMA control (and blitter status) read
INTREQR EQU $1E ;Interrupt request bits read
BLTCON0 EQU $40 ;Blitter control register 0
BLTCON1 EQU $42 ;Blitter control register 1
BLTAFWM EQU $44 ;Blitter first word mask for source A
BLTCPTH EQU $48 ;Blitter ptr to source C (high 3 bits)
BLTAPTH EQU $50 ;Blitter ptr to source A (high 3 bits)
BLTAPTL EQU $52 ;Blitter ptr to source A (low 15 bits)
BLTDPTH EQU $54 ;Blitter ptr to destn. D (high 3 bits)
BLTSIZE EQU $58 ;Blitter start and size (width, height)
BLTCMOD EQU $60 ;Blitter modulo for source C
BLTBMOD EQU $62 ;Blitter modulo for source B
BLTAMOD EQU $64 ;Blitter modulo for source A
BLTDMOD EQU $66 ;Blitter modulo for destn. D
BLTBDAT EQU $72 ;Blitter source B data register
BLTADAT EQU $74 ;Blitter source A data register
COP1LCH EQU $80 ;Copper 1st location reg (high 3 bits)
DIWSTRT EQU $8E ;Display window start
DIWSTOP EQU $90 ;Display window stop
DDFSTRT EQU $92 ;Display bit plane data fetch start
DDFSTOP EQU $94 ;Display bit plane data fetch stop
DMACON EQU $96 ;DMA control write (clear or set)
INTENA EQU $9A ;Interrupt enable bits (clear or set)
INTREQ EQU $9C ;Interrupt request bits (clear or set)
BPLCON0 EQU $100 ;Bit plane control register 0
BPLCON1 EQU $102 ;Bit plane control register 1
BPLCON2 EQU $104 ;Bit plane control register 2
BPL1MOD EQU $108 ;Bit plane modulo (odd planes)
BPL2MOD EQU $10A ;Bit plane modulo (even planes)
COLOR00 EQU $180 ;Color register 00
COLOR01 EQU $182 ;Color register 01
CIAA EQU $BFE001 ;Base address of 8520-A
TALO EQU $400 ;Timer A low byte
TAHI EQU $500 ;Timer A high byte
SDR EQU $C00 ;Serial data register
ICR EQU $D00 ;Interrupt control register
CRA EQU $E00 ;Control register A
;----------------------------------------------------------------------
;Routine to initialize the Amiga keyboard.
;
OPENI MOVE.L A2,-(SP) ;Save registers
CLR.B KEYDOWN.L ;Assume all keys are up
ST CHKUSRF ;Enable CHKUSR (CTRL-C = abort, etc.)
;Set up timer A for shifting out the keyboard handshake signal
LEA CIAA.L,A2
CLR.B CRA(A2) ;Set serial input, timer A off
MOVE.B #$7F,ICR(A2) ;Clear all interrupts
MOVE.B #$88,ICR(A2) ;Set interrupts on serial port
; MOVE.B #$FF,SDR(A2) ;Set handshake signal (true low)
; TST.B SDR(A2) ;Flush anything in the registers
; TST.B SDR(A2) ; by reading them
; BRA XXXX ;DEBUG
LEA KEYSTRT-@-2(PC),A2 ;Set the keyboard buffer empty
MOVE.L A2,KEYFILL.L
MOVE.L A2,KEYEMTY.L
; SUBA.L A2,A2 ;A2:= 0
;LOOP MOVE.L #IRQ1HAN,(A2)+ ;Spurious
; CMPA.W #$0100,A2
; BLO.S LOOP
; MOVE.L #IRQ1HAN,$64 ;1
MOVE.L #IRQ2HAN,$68 ;2 set up interrupt vector for CIAA
; MOVE.L #IRQ3HAN,$6C ;3
; MOVE.L #IRQ4HAN,$70 ;4
; MOVE.L #IRQ5HAN,$74 ;5
MOVE.L #IRQ6HAN,$78 ;6 ignore spurious timer interrupt
; MOVE.L #IRQ7HAN,$7C ;7
MOVE.L #IRQ6HAN,$80 ;TRAP 0 DEBUG
LEA CHIPREG.L,A2
MOVE.W #$7FFF,INTENA(A2) ;Off
MOVE.W #$C008,INTENA(A2) ;INT2*
ANDI.W #$F0FF,SR ;Enable interrupts from keyboard
;XXXX ;DEBUG
MOVEA.L (SP)+,A2
RTS
;Dummy interrupt handlers -- just hang.
IRQ1HAN
;IRQ2HAN
IRQ3HAN
IRQ4HAN
IRQ5HAN
IRQ6HAN
IRQ7HAN
BRA IRQ2HAN
;----------------------------------------------------------------------
;Routine to initialize the Amiga display.
; (Note that INTA.68K routines destroy registers D0 and A6.)
;
OPENO MOVEM.L D0/A1/A2/A5/A6,-(SP) ;Save registers
LEA CHIPREG.L,A2 ;Point to chip registers
LEA INFO.L,A1 ;Point to INFO array
MOVE.W 5*4(A1),COLOR00(A2) ;Get color register values from
MOVE.W 5*4+2(A1),COLOR01(A2) ; INFO array
LEA PARAMS1-@-2(PC),A5 ;Point A5 to parameters
JSR BITMAP ;BITMAP(SCREEN, WIDTH, HEIGHT, DEPTH);
LEA PARAMS2-@-2(PC),A5 ;Point A5 to parameters
JSR BITMAP2 ;BITMAP2(MAGNIFICATIONX,Y, OFFSETX,Y,
; INVERTX,Y)
LEA PARAMS3-@-2(PC),A5 ;Point A5 to parameters
JSR VIEW ;VIEW(SCREEN, BPLCON0)
MOVE.W WIDTH+2,D0 ;CONWIDE:= WIDTH/8
ASR.W #3,D0 ;(FWIDTH = 8)
MOVE.B D0,CONWIDE
MOVE.L HEIGHT,D0 ;CONHIGH:= HEIGHT/FHEIGHT
DIVU FHEIGHT+2.L,D0
MOVE.B D0,CONHIGH
MOVEM.L (SP)+,D0/A1/A2/A5/A6 ;Restore registers
RTS
;BITMAP(SCREEN, WIDTH, HEIGHT, DEPTH)
PARAMS1 DC.L SCREEN, 640, 240, 1
;BITMAP2(MAGNIFICATIONX,Y, OFFSETX,Y, INVERTX,Y)
PARAMS2 DC.L 0, 0, 0, 0, FALSE, FALSE
;VIEW(SCREEN, $9004)
PARAMS3 DC.L SCREEN, $9000 ;Hires, one bit plane
;----------------------------------------------------------------------
;Output the character in D0 and bump the cursor position, scroll if
; necessary.
;
BYTEOUT MOVEM.L D0-D1/A0-A1,-(SP) ;Save registers
BSR CHKUSR ;Check for CTRL-C etc.
MOVEQ #0,D1 ;Point A0 to character in font table
MOVE.B D0,D1 ;A0= (D0 - $20) *8 + FONT
SUBI.B #$20,D1
LSL.W #3,D1 ;*8, font is 8 dots wide
LEA FONT.L,A0
LEA 0(A0,D1.W),A0
LEA CHIPREG.L,A1 ;Set register base (it's efficient)
BYO05 MOVE.W DMACONR(A1),D0 ;Wait for blitter not busy
BTST #14,D0 ;(Don't display anything while
BNE.S BYO05 ; the screen might be clearing)
MOVE.W X0+2,D1 ;Is cursor in the middle of a byte?
MOVE.W D1,D0
ANDI.W #$0007,D0
BNE BYO10 ;Branch if so
;Normal case: X position is on a byte boundary
;A0 points character's graphics in the FONT table
MOVE.W Y0+2,D0 ;Point A1 to position on RASTER
MULU WIDTH+2,D0 ;A1:= Y0 *WIDTH/8 + X0 /8 + RASTER
LSR.L #3,D0
ASR.W #3,D1
ADD.W D1,D0
ADD.L RASTER,D0
MOVEA.L D0,A1
MOVE.L WIDTH,D0 ;Amount to add to move down a pixel
LSR.L #3,D0 ;WIDTH/8
MOVEQ #7,D1 ;For D1:= 7 downto 0 do...
BYO07 MOVE.B (A0)+,(A1) ;Move 8 bytes from FONT table to RASTER
ADDA.L D0,A1
DBF D1,BYO07
BRA BYO90 ;Exit
BYO10
MOVEM.L D2-D5,-(SP) ;Save extra registers
; Register usage:
; D2 = Number of bits to shift right
; D3 = Mask
; D4 = Amount to add to screen address to move down a pixel
; D5 = Loop counter
MOVE.W X0+2,D2
AND.W #$000F,D2 ;D2= number of times to shift font right
MOVE.L #$00FFFFFF,D3 ;Set up mask (FWIDTH = 8)
ROR.L D2,D3 ;Shift notch into position
MOVE.W Y0+2,D0 ;Point A1 to the long word on RASTER
MULU WIDTH+2,D0 ; which will contain the font graphics
LSR.L #3,D0 ;A1:= Y0 *WIDTH/8 + (X0 /8 &$FFFE) +
MOVE.W X0+2,D1 ; RASTER
ASR.W #3,D1
ANDI.W #$FFFE,D1 ;A1 must point to a word boundary
ADD.W D1,D0 ; because of the way the 68000 accesses
ADD.L RASTER,D0 ; memory
MOVEA.L D0,A1
MOVE.L WIDTH,D4 ;Amount to add to move down a pixel
LSR.L #3,D4 ;D4:= WIDTH/8
MOVEQ #7,D5 ;For D5:= 0 to 5 do...
BYO20 MOVEQ #0,D0 ;Clear high bytes
MOVE.B (A0)+,D0 ;Get a byte of font graphics
ROR.L #8,D0 ;Shift it into position
LSR.L D2,D0
MOVE.L (A1),D1 ;Get long word from screen
AND.L D3,D1 ;Mask out a place for font
OR.L D0,D1 ;Combine font with screen bits
MOVE.L D1,(A1) ;Store back on screen
ADDA.L D4,A1 ;Move down a pixel
DBF D5,BYO20 ;Loop
MOVEM.L (SP)+,D2-D5 ;Restore extra registers
BYO90 MOVEM.L (SP)+,D0-D1/A0-A1 ;Restore registers
ADDI.W #8,X0+2 ;Move cursor ahead 8 pixels
;(PFALL) Fall into SCROLL routine
;----------------------------------------------------------------------
;Check for scroll and do it if necessary.
;
SCROLL MOVE.W D0,-(SP) ;Save D0.W
MOVE.W X0+2,D0 ;Is the cursor beyond the end of line?
ADDQ.W #7,D0 ;Don't break character in half
CMP.W WIDTH+2,D0
BLO.S SCR20 ;Branch if not
CLR.W X0+2 ;Move to the beginning of the next line
MOVE.W FHEIGHT+2.L,D0
ADD.W D0,Y0+2
SCR20
MOVE.W Y0+2,D0 ;Is the cursor beyond the bottom line?
ADDI.W #9,D0 ;Don't break character in half
CMP.W HEIGHT+2,D0
BLO.S SCR40 ;Branch if not.
BSR.S SCROLLX ;Scroll the screen up one line
MOVE.W HEIGHT+2,D0 ;Set cursor to the bottom line
SUB.W FHEIGHT+2.L,D0 ;Y0:= HEIGHT - FHEIGHT
MOVE.W D0,Y0+2
SCR40
MOVE.W (SP)+,D0 ;Restore D0.W
RTS
;----------------------------------------------------------------------
;Scroll the screen up one line and blank the bottom line. This uses the
; blitter.
;
SCROLLX MOVEM.L D0-D1/A0,-(SP) ;Save registers
LEA CHIPREG.L,A0 ;Set register base (it's efficient)
MOVE.W #$8440,DMACON(A0) ;Enable blitter DMA (be nasty)
SCRX10 MOVE.W DMACONR(A0),D0 ;Wait for blitter not busy
BTST #14,D0 ;(Don't change the blitter registers
BNE.S SCRX10 ; while it's doing something)
MOVE.W WIDTH+2,D0 ;Point to 2nd text line
LSR.W #3,D0 ;RASTER + WIDTH/8 *FHEIGHT
MULU FHEIGHT+2.L,D0
ADD.L RASTER,D0
MOVE.L D0,BLTAPTH(A0)
MOVE.L RASTER,BLTDPTH(A0) ;Point destn. to 1st text line
MOVEQ #0,D0
MOVE.W D0,BLTAMOD(A0) ;Modulo = 0
MOVE.W D0,BLTDMOD(A0)
MOVE.W D0,BLTCON1(A0)
MOVEQ #$FFFFFFFF,D0 ;No masking
MOVE.L D0,BLTAFWM(A0) ;(Also sets BLTALWM)
MOVE.W #$09F0,BLTCON0(A0) ;Use A & D, D:= A
MOVE.W HEIGHT+2,D0 ;(HEIGHT - FHEIGHT) << 6 + WIDTH/16
SUB.W FHEIGHT+2.L,D0
LSL.W #6,D0
MOVE.W WIDTH+2,D1
LSR.W #4,D1
OR.W D1,D0
MOVE.W D0,BLTSIZE(A0)
SCRX20 MOVE.W DMACONR(A0),D0 ;Wait for blitter not busy
BTST #14,D0 ;(Don't change the blitter registers
BNE.S SCRX20 ; while it's doing something)
MOVE.W #$0100,BLTCON0(A0) ;Use D
MOVE.W FHEIGHT+2.L,D0 ;FHEIGHT << 6 + WIDTH/16
LSL.W #6,D0
MOVE.W WIDTH+2,D1
LSR.W #4,D1
OR.W D1,D0
MOVE.W D0,BLTSIZE(A0)
SCRX30 MOVE.W DMACONR(A0),D0 ;Wait for blitter not busy
BTST #14,D0 ;(Don't allow writting while it's being
BNE.S SCRX30 ; cleared)
MOVEM.L (SP)+,D0-D1/A0 ;Restore registers
RTS
;----------------------------------------------------------------------
;Make a beep noise. Approximately 1KHz for 0.1 second.
; (The hardware manual lies: the processor cannot control sound by
; writing directly to AUDXDAT.)
;
AUD0LC EQU $A0 ;Pointer to waveform table (18 bits)
AUD0LEN EQU $A4 ;Length of waveform table (words)
AUD0PER EQU $A6 ;Sample period, 280ns per count
AUD0VOL EQU $A8 ;Audio channel volume control
BEEP MOVEM.L D0/A0,-(SP) ;Save registers
LEA CHIPREG.L,A0 ;Point to base of chip registers
MOVE.L #WAVETBL,AUD0LC(A0) ;Set pointer to wave table
MOVE.W #4,AUD0LEN(A0) ;Set table length (words)
MOVE.W #446,AUD0PER(A0) ;Set sample period (446 *280ns)
MOVE.W #$0040,AUD0VOL(A0) ;Set maximum volume
MOVE.W #$8201,DMACON(A0) ;Enable audio channel 0 DMA
MOVEQ #-1,D0 ;Delay about 0.1 second
BEEP10 DBF D0,BEEP10
MOVE.W #$0001,DMACON(A0) ;Disable audio channel 0 DMA
MOVEM.L (SP)+,D0/A0 ;Restore registers
RTS
WAVETBL DC.W $0060, $7F60, $00E0, $80E0
;----------------------------------------------------------------------
;Character fonts for 8 x 8 cells.
; Format:
; MSB LSB
; first byte . . * * * * . .
; . * . . . . * .
; . . . . . . * .
; . . . * * * . .
; . . * . . . . .
; . * . . . . . .
; . * * * * * * .
; last byte . . . . . . . .
;
;
FHEIGHT DC.L 10 ;Height of font including space between lines
;FWIDTH DC.L 8 ;Not used - width is cast in concrete
FONT
; DC.B $00, $00, $FF, $00, $00, $FF, $00, $00 ;===
; DC.B $10, $10, $1F, $10, $10, $1F, $10, $10 ; |=
; DC.B $10, $10, $FF, $10, $10, $FF, $10, $10 ;=|=
; DC.B $10, $10, $F0, $10, $10, $F0, $10, $10 ;=|
; DC.B $01, $02, $04, $08, $10, $20, $40, $80 ; /
; DC.B $80, $40, $20, $10, $08, $04, $02, $01 ; \
; DC.B $81, $42, $24, $18, $18, $24, $42, $81 ; x
; DC.B $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF ;block (cursor)
; DC.B $00, $20, $40, $FE, $40, $20, $00, $00 ;<--
; DC.B $0C, $12, $12, $12, $0C, $00, $00, $00 ; 0
; DC.B $10, $10, $10, $10, $54, $38, $10, $00 ;down arrow
; DC.B $10, $38, $54, $10, $10, $10, $10, $00 ;up arrow
; DC.B $00, $08, $04, $FE, $04, $08, $00, $00 ;-->
; DC.B $0C, $12, $04, $08, $1E, $00, $00, $00 ; 2
; DC.B $10, $10, $10, $F0, $00, $00, $00, $00 ;low-rt corner
; DC.B $10, $10, $10, $FF, $10, $10, $10, $10 ; +
;
; DC.B $10, $10, $10, $FF, $00, $00, $00, $00 ;-'-
; DC.B $00, $00, $00, $FF, $10, $10, $10, $10 ;-,-
; DC.B $10, $10, $10, $F0, $10, $10, $10, $10 ;-|
; DC.B $10, $10, $10, $1F, $10, $10, $10, $10 ; |-
; DC.B $FF, $00, $00, $00, $00, $00, $00, $00 ;---
; DC.B $00, $00, $00, $FF, $00, $00, $00, $00 ;---
; DC.B $10, $10, $10, $10, $10, $10, $10, $10 ; |
; DC.B $01, $01, $01, $01, $01, $01, $01, $01 ; |
; DC.B $00, $00, $00, $1F, $10, $10, $10, $10 ;up-lt corner
; DC.B $00, $00, $00, $F0, $10, $10, $10, $10 ;up-rt corner
; DC.B $10, $10, $10, $1F, $00, $00, $00, $00 ;low-lt corner
; DC.B $10, $10, $10, $F0, $00, $00, $00, $00 ;low-rt corner
; DC.B $00, $00, $00, $03, $04, $08, $10, $10 ;up-lt curve
; DC.B $00, $00, $00, $80, $40, $20, $10, $10 ;up-rt curve
; DC.B $10, $08, $04, $03, $00, $00, $00, $00 ;low-lt curve
; DC.B $10, $20, $40, $80, $00, $00, $00, $00 ;low-rt curve
;
DC.B $00, $00, $00, $00, $00, $00, $00, $00 ;space
DC.B $18, $18, $18, $18, $18, $00, $18, $00 ;!
DC.B $6C, $6C, $00, $00, $00, $00, $00, $00 ;"
DC.B $6C, $6C, $FE, $6C, $FE, $6C, $6C, $00 ;#
DC.B $18, $3E, $68, $3C, $16, $7C, $18, $00 ;$
DC.B $00, $C6, $CC, $18, $30, $66, $C6, $00 ;%
DC.B $38, $6C, $6C, $38, $7A, $CC, $76, $00 ;&
DC.B $38, $18, $30, $00, $00, $00, $00, $00 ;'
DC.B $0C, $18, $30, $30, $30, $18, $0C, $00 ;(
DC.B $30, $18, $0C, $0C, $0C, $18, $30, $00 ;)
DC.B $00, $66, $3C, $7E, $3C, $66, $00, $00 ;*
DC.B $00, $18, $18, $7E, $18, $18, $00, $00 ;+
DC.B $00, $00, $00, $00, $00, $38, $18, $30 ;,
DC.B $00, $00, $00, $7E, $00, $00, $00, $00 ;-
DC.B $00, $00, $00, $00, $00, $18, $18, $00 ;.
DC.B $00, $06, $0C, $18, $30, $60, $C0, $00 ;/
DC.B $3C, $66, $6E, $7E, $76, $66, $3C, $00 ;0
DC.B $18, $38, $18, $18, $18, $18, $3C, $00 ;1
DC.B $3C, $66, $06, $0C, $38, $60, $7E, $00 ;2
DC.B $7E, $0C, $18, $3C, $06, $66, $3C, $00 ;3
DC.B $0E, $1E, $36, $66, $7F, $06, $06, $00 ;4
DC.B $7E, $60, $7C, $06, $06, $66, $3C, $00 ;5
DC.B $1C, $30, $60, $7C, $66, $66, $3C, $00 ;6
DC.B $7E, $46, $06, $0C, $18, $18, $18, $00 ;7
DC.B $3C, $66, $66, $3C, $66, $66, $3C, $00 ;8
DC.B $3C, $66, $66, $3E, $0C, $18, $30, $00 ;9
DC.B $00, $18, $18, $00, $18, $18, $00, $00 ;:
DC.B $00, $18, $18, $00, $18, $18, $18, $30 ;;
DC.B $0C, $18, $30, $60, $30, $18, $0C, $00 ;<
DC.B $00, $00, $7E, $00, $7E, $00, $00, $00 ;=
DC.B $60, $30, $18, $0C, $18, $30, $60, $00 ;>
DC.B $3C, $66, $06, $0C, $18, $00, $18, $00 ;?
DC.B $3C, $66, $6E, $6A, $6E, $60, $3C, $00 ;@
DC.B $18, $3C, $66, $66, $7E, $66, $66, $00 ;A
DC.B $7C, $66, $66, $7C, $66, $66, $7C, $00 ;B
DC.B $3C, $66, $60, $60, $60, $66, $3C, $00 ;C
DC.B $78, $6C, $66, $66, $66, $6C, $78, $00 ;D
DC.B $7E, $60, $60, $7C, $60, $60, $7E, $00 ;E
DC.B $7E, $60, $60, $7C, $60, $60, $60, $00 ;F
DC.B $3E, $60, $60, $60, $6E, $66, $3E, $00 ;G
DC.B $66, $66, $66, $7E, $66, $66, $66, $00 ;H
DC.B $3C, $18, $18, $18, $18, $18, $3C, $00 ;I
DC.B $06, $06, $06, $06, $06, $66, $3C, $00 ;J
DC.B $66, $6C, $78, $70, $78, $6C, $66, $00 ;K
DC.B $60, $60, $60, $60, $60, $60, $7E, $00 ;L
DC.B $C6, $EE, $FE, $D6, $C6, $C6, $C6, $00 ;M
DC.B $66, $66, $76, $7E, $6E, $66, $66, $00 ;N
DC.B $3C, $66, $66, $66, $66, $66, $3C, $00 ;O
DC.B $7C, $66, $66, $7C, $60, $60, $60, $00 ;P
DC.B $3C, $66, $66, $66, $66, $6E, $3C, $06 ;Q
DC.B $7C, $66, $66, $7C, $78, $6C, $66, $00 ;R
DC.B $3C, $66, $60, $3C, $06, $66, $3C, $00 ;S
DC.B $7E, $18, $18, $18, $18, $18, $18, $00 ;T
DC.B $66, $66, $66, $66, $66, $66, $3C, $00 ;U
DC.B $66, $66, $66, $3C, $3C, $18, $18, $00 ;V
DC.B $C6, $C6, $C6, $D6, $EE, $C6, $82, $00 ;W
DC.B $66, $66, $3C, $18, $3C, $66, $66, $00 ;X
DC.B $66, $66, $66, $3C, $18, $18, $18, $00 ;Y
DC.B $7E, $06, $0C, $18, $30, $60, $7E, $00 ;Z
DC.B $3C, $30, $30, $30, $30, $30, $3C, $00 ;[
DC.B $00, $C0, $60, $30, $18, $0C, $06, $00 ;\
DC.B $3C, $0C, $0C, $0C, $0C, $0C, $3C, $00 ;]
DC.B $10, $38, $6C, $C6, $00, $00, $00, $00 ;^
DC.B $00, $00, $00, $00, $00, $00, $00, $FE ;_
DC.B $38, $30, $18, $00, $00, $00, $00, $00 ;`
DC.B $00, $00, $3C, $06, $3E, $66, $3F, $00 ;a
DC.B $60, $60, $7C, $66, $66, $66, $7C, $00 ;b
DC.B $00, $00, $3C, $66, $60, $62, $3C, $00 ;c
DC.B $06, $06, $3E, $66, $66, $66, $3E, $00 ;d
DC.B $00, $00, $3C, $66, $7E, $60, $3E, $00 ;e
DC.B $1E, $30, $30, $7C, $30, $30, $30, $00 ;f
DC.B $00, $00, $3E, $66, $66, $3E, $06, $7C ;g
DC.B $60, $60, $7C, $66, $66, $66, $66, $00 ;h
DC.B $18, $00, $38, $18, $18, $18, $3C, $00 ;i
DC.B $0C, $00, $0C, $0C, $0C, $0C, $CC, $78 ;j
DC.B $60, $60, $66, $6C, $78, $6C, $66, $00 ;k
DC.B $38, $18, $18, $18, $18, $18, $3C, $00 ;l
DC.B $00, $00, $CC, $EE, $D6, $C6, $C6, $00 ;m
DC.B $00, $00, $7C, $66, $66, $66, $66, $00 ;n
DC.B $00, $00, $3C, $66, $66, $66, $3C, $00 ;o
DC.B $00, $00, $7C, $66, $66, $7C, $60, $60 ;p
DC.B $00, $00, $3E, $66, $66, $3E, $06, $06 ;q
DC.B $00, $00, $6E, $70, $60, $60, $60, $00 ;r
DC.B $00, $00, $3E, $60, $3C, $06, $7C, $00 ;s
DC.B $10, $30, $7C, $30, $30, $32, $1C, $00 ;t
DC.B $00, $00, $66, $66, $66, $66, $3B, $00 ;u
DC.B $00, $00, $66, $66, $66, $3C, $18, $00 ;v
DC.B $00, $00, $C6, $C6, $D6, $7C, $6C, $00 ;w
DC.B $00, $00, $C6, $6C, $38, $6C, $C6, $00 ;x
DC.B $00, $00, $66, $66, $66, $3C, $18, $70 ;y
DC.B $00, $00, $7E, $0C, $18, $30, $7E, $00 ;z
DC.B $0E, $18, $18, $70, $18, $18, $0E, $00 ;{
DC.B $18, $18, $18, $00, $18, $18, $18, $00 ;|
DC.B $70, $18, $18, $0E, $18, $18, $70, $00 ;}
DC.B $72, $9C, $00, $00, $00, $00, $00, $00 ;~
DC.B $33, $CC, $33, $CC, $33, $CC, $33, $CC ;box
;======================================================================
;Keyboard routines:
;----------------------------------------------------------------------
;Wait for a keystroke then return its ASCII value in D0.
; This uses an interrupt handler to fill a circular (type-ahead) buffer.
;
GETKEY MOVE.L A0,-(SP) ;Save A0
MOVEA.L KEYEMTY-@-2(PC),A0 ;Get ASCII key from circular buffer
KI10 ADDQ.L #1,HASH ;Spin the randomizer while we wait
CMPA.L KEYFILL-@-2(PC),A0 ;Is there something in the buffer?
BEQ.S KI10 ;Branch if not -- wait for key code
MOVEQ #0,D0 ;Make sure high-order bytes are clear
MOVE.B (A0)+,D0 ;Get key code and bump empty pointer
CMPA.L #KEYEND,A0 ;Did empty pointer go beyond the end?
BLO.S KI30 ;Branch if not
LEA KEYSTRT-@-2(PC),A0 ;Wrap empty pointer to beginning
KI30 MOVE.L A0,KEYEMTY.L ;Save empty pointer
MOVEA.L (SP)+,A0 ;Restore A0
RTS ;Return with ASCII code in D0
;----------------------------------------------------------------------
;Routine to check if a key was struck. This returns with NE status if
; it was struck. A boolean is also returned in D0 since this may be
; called by an intrinsic. (Qualifier keys, such as SHIFT and CTRL, don't
; count as keystrokes.)
;
KEYHIT MOVE.L KEYFILL-@-2(PC),D0
KH10 CMP.L KEYEMTY-@-2(PC),D0
SNE D0
EXT.W D0
EXT.L D0
RTS
REPRATE EQU $7FFF ;Auto-repeat repitition rate
; (1000 => 16.6/sec))
KEYFLAG DC.B 0 ;Bit array indicating key down for
; SHIFT, CAPS, CTRL, ALT and A keys
KEYLAST DC.B 0 ;Last ASCII key (for auto-repeat)
KEYDOWN DC.B 0 ;Flag: ASCII key is pressed
KEYFILL DS.L 1 ;Pointer used to fill circular buffer
KEYEMTY DS.L 1 ;Pointer used to empty circular buffer
KEYSTRT DS.B 10 ;Circular (type-ahead) buffer
KEYEND EQU @ ;End of buffer +1
;----------------------------------------------------------------------
;Keyboard interrupt handler. This routine gets the key code, converts
; it to ASCII, and stores it into a circular buffer.
;
;The A keys are used as auto-repeat keys.
; Pressing SHIFT while CAPS LOCK is true, will give lowercase letters.
;
;The hysterical, insubordinate keyboard must be given immediate
; attention otherwise it will make some mighty assumptions for a mere
; keyboard and go into resync mode, which will cause delays and false
; key codes. This is a typical example of how an intelligent peripherial
; out-smarts itself. This requires that an interrupt handler be used,
; which serendipitously provides a type-ahead buffer.
;
IRQ2HAN MOVEM.L D0/D1/A0,-(SP) ;Save registers
LEA CHIPREG.L,A0 ;Point A0 to base of chip registers
MOVE.W #$0008,INTREQ(A0) ;Clear interrupt request
; ADDQ.W #3,COLOR00(A0) ;*** DEBUG ***
LEA CIAA.L,A0 ;Point A0 to base address of 8520-A
MOVE.B ICR(A0),D0 ;Get copy and clear interrupt bits
BTST #3,D0 ;Serial data received?
BEQ KB200 ;Branch if not
MOVE.W D0,-(SP) ;Save interrupt status bits
MOVEQ #0,D0 ;Clear high bytes (for index below)
MOVE.B SDR(A0),D0 ;Read data from keyboard serial port
ORI.B #$40,CRA(A0) ;Set to output from serial port
; (handshake signal)
NOT.B D0 ;Re-invert the data
ROR.B #1,D0 ;Unscramble the bits
CMPI.B #$80,D0 ;Is it a release, (or comm?)
BLO.S KB10 ;Branch if not
CMPI.B #$E0,D0 ;Is it a comm or modifier?
BHS.S KB10 ;Branch if so
CLR.B KEYDOWN.L ;Clear KEYDOWN to stop auto-repeat
KB10
CMPI.B #$60,D0 ;Is it a qualifier, release, or comm?
BLO.S KB20 ;Branch if not
MOVE.B D0,D1 ;Is it a qualifier key?
ANDI.B #$7F,D1 ; (i.e: $60-$67 or $E0-$E7)
CMPI.B #$60,D1
BLO KB100 ;Branch if not
CMPI.B #$67,D1
BHI KB100
;Set or clear the flag bit which
SUBI.B #$60,D0 ; corresponds to this qualifier key
BCLR #7,D0 ;D0: [0..7]
BEQ.S KB15 ;Branch if MSB was clear
BCLR D0,KEYFLAG.L ;Key was released, clear flag bit
BRA.S KB18
KB15 BSET D0,KEYFLAG.L ;Key was pressed, set flag bit
KB18 BRA KB100
KB20
CMPI.B #$50,D0 ;Is it a function or HELP key?
BLO.S KB30 ;Branch if not
BRA KB100 ;Ignore it
KB30
CMPI.B #$40,D0 ;Is it a control key?
BLO.S KB40 ;Branch if not
LEA KBTBL2.L,A0 ;Look up control keys in table
SUBI.B #$40,D0 ;Warning: high byte must be clear
MOVE.B 0(A0,D0.W),D0
BRA KB80 ;Exit, checking for ALT key
KB40
BTST #0,KEYFLAG.L ;Is the left SHIFT key down?
BNE.S KB41 ;Branch if it is
BTST #1,KEYFLAG.L ;Is the right SHIFT key down?
BEQ.S KB50 ;Branch if not
KB41
LEA KBTBL1.L,A0 ;Look up shifted character
MOVE.B 0(A0,D0.W),D0 ;WARNING (high byte must be clear)
BRA.S KB60 ;Go check for CAPS LOCK key
KB50
LEA KBTBL0.L,A0 ;Look up character
MOVE.B 0(A0,D0.W),D0
KB60
BTST #2,KEYFLAG.L ;Is the CAPS LOCK key down?
BEQ.S KB70 ;Branch if not
CMPI.B #'a',D0 ;Is character a lowercase letter?
BLO.S KB65 ;Branch if not
CMPI.B #'z',D0
BHI.S KB65
ANDI.B #$DF,D0 ;Convert to upper case
BRA.S KB70
KB65
CMPI.B #'A',D0 ;Is character an uppercase letter?
BLO.S KB70 ;Branch if not
CMPI.B #'Z',D0
BHI.S KB70
ORI.B #$20,D0 ;Convert to lower case
KB70
BTST #3,KEYFLAG.L ;Is the CTRL key down?
BEQ.S KB80 ;Branch if not
CMPI.B #$38,D0 ;If CTRL-8 then toggle interlaced mode
BNE.S KB74
MOVE.W #240,D0 ;Assume toggle into non-interlaced mode
BCHG #2,PARAMS3+7.L ;Test LACE bit in BPLCON0 word
BNE.S KB72 ;Branch if it was in LACE mode
ADD.W D0,D0 ;Double height for LACE mode
KB72 MOVE.W D0,PARAMS1+10.L ;Set height parameter
BRA.S KB77 ;Go open display with new parameters
KB74
CMPI.B #$39,D0 ;If CTRL-9 then toggle hires mode
BNE.S KB78
MOVE.W #320,D0 ;Assume toggle into lores mode
BCHG #7,PARAMS3+6.L ;Test HIRES bit in BPLCON0 word
BNE.S KB76 ;Branch if it was in HIRES mode
ADD.W D0,D0 ;Double width for hires mode
KB76 MOVE.W D0,PARAMS1+6.L ;Set width parameter
KB77 BSR OPENO1 ;Open display with new parameters
BRA KB100 ;Exit
KB78
CMPI.B #$40,D0 ;If $40-$7E then clear bits 5 & 6
BLO.S KB80 ; to make it a control character
CMPI.B #$7E,D0
BHI.S KB80
ANDI.B #$9F,D0
KB80
BTST #4,KEYFLAG.L ;Is the left ALT key down?
BNE.S KB81 ;Branch if it is
BTST #5,KEYFLAG.L ;Is the right ALT key down?
BEQ.S KB90 ;Branch if not
KB81
ORI.B #$80,D0 ;Set MSB
KB90
MOVE.B D0,KEYLAST.L ;Save this ASCII key character in case
ST KEYDOWN.L ; of auto-repeat
BSR KEY2BUF ;Store key character in buffer
;If auto-repeat key is down and an ASCII key is pressed then enable
; auto-repeat interrupts.
KB100 LEA CIAA.L,A0 ;Point A0 to base address of 8520-A
TST.B KEYDOWN.L ;Is an ASCII key down?
BEQ.S KB120 ;Branch if not
BTST #6,KEYFLAG.L ;Is an auto-repeat key down?
BNE.S KB110 ;Branch if it is
BTST #7,KEYFLAG.L
BEQ.S KB120 ;Branch if not
KB110 MOVE.B #REPRATE/256,TAHI(A0) ;Set timer repitition rate
MOVE.B #REPRATE\256,TALO(A0)
MOVE.B #$41,CRA(A0) ;Start timer, force load, 02 input
MOVE.B #$81,ICR(A0) ;Enable timer A interrupts
BRA.S KB130
KB120
CLR.B CRA(A0) ;Stop timer
KB130
MOVEQ #75,D0 ;Wait a total of 75us (barf) for the
KB140 DBF D0,KB140 ; handshake signal
ANDI.B #$BF,CRA(A0) ;Set to input from serial port
MOVE.W (SP)+,D0 ;Restore interrupt bits
;Check for auto-repeat interrupt
KB200 BTST #0,D0 ;Timer A interrupt?
BEQ.S KB230 ;Branch if not
TST.B KEYDOWN.L ;Is an ASCII key down?
BEQ.S KB230 ;Branch if not
MOVE.B KEYLAST-@-2(PC),D0 ;Get the last ASCII key code
BSR KEY2BUF ;Put it into the circular buffer
KB230
MOVEM.L (SP)+,D0/D1/A0 ;Restore registers
RTE
;These tables use the key code as an index to the ASCII equivalent.
;Table of unshifted characters (key codes $00-$3F):
KBTBL0 ASCII "`1234567890-=\?0"
ASCII "qwertyuiop[]?123"
ASCII "asdfghjkl;'??456"
ASCII "?zxcvbnm,./?.789"
;Table of shifted characters (key codes $00-$3F).
; Shifted keypad characters are IBM-style ED commands.
KBTBL1 ASCII "~!@#$%^&*()_+|?"
DC.B $02 ;Word back
ASCII "QWERTYUIOP{}?"
DC.B $04, $13, $0A ;End, line down, page down
ASCII 'ASDFGHJKL:"??'
DC.B $11, $14, $01 ;Back char, show controls, char ahead
ASCII "?ZXCVBNM<>??"
DC.B $0E, $05, $17, $0B ;Word ahead, start, line up, page up
;Table of control characters (key codes $40-$4F):
KBTBL2 DC.B $20, $08, $09, $0D, $0D, $1B, $7F, $00
DC.B $00, $00, $2D, $00, $0B, $0A, $15, $08
;----------------------------------------------------------------------
;Store D0 into circular buffer (if it isn't full).
; Register A0 is destroyed.
;
KEY2BUF MOVEA.L KEYFILL-@-2(PC),A0 ;Store character into circular buffer
MOVE.B D0,(A0)+ ;Always store the character
CMPA.L #KEYEND,A0 ;Is the fill pointer beyond the end?
BLO.S KBF20 ;Branch if not
LEA KEYSTRT-@-2(PC),A0 ;Wrap fill pointer back to beginning
KBF20 CMPA.L KEYEMTY-@-2(PC),A0 ;Is the buffer full?
BEQ.S KBF30 ;Branch if it is -- don't increment ptr
MOVE.L A0,KEYFILL.L ;Save fill pointer
KBF30
RTS
END EQU @-1 ;Address where this handler ends
IF @ > MEMTOP - $180
ERROR -- FILE IS TOO LONG (NEED ROOM FOR SYSTEM STACK)
ELSE
DCB.B MEMTOP-@, 0 ;Fill the rest of the block with zeros
ENDIF
;----------------------------------------------------------------------
;Hook these handlers into the device handler table as devices 0 and 1.
;
ORG DEVTBL
DC.L CONHAN0
DC.L CONHAN1
END
;Hook these handlers into t